#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QList>
#include <QPrinter>
#include <QAction>
#include <QFileInfo>
#include <QErrorMessage>
#include <QImageReader>
#include <QImageWriter>
#include <QFileDialog>
#include <QLabel>
#include <QStatusBar>
#include <QInputDialog>
#include <QtEvents>
#include <QMenu>
#include <QMenuBar>
#include <QDockWidget>
#include <QPushButton>
#include <QSettings>
#include <QGroupBox>
#include <QSlider>
#include <QProgressDialog>
#include <iostream>
#include <string>

#include "imagescene.h"
#include "resizedialog.h"
#include "histogramwidget.h"
#include "customconvolutiondialog.h"
#include "thgraphicscropitem.h"
#include "THGraphicsMergeItem.h"
#include "limage.h"
#include "filter.h"
#include "blur.h"
#include "sharpen.h"
#include "enhance.h"
#include "edgedetection.h"
#include "gaussianblur.h"
#include "emboss.h"
#include "sobelfilter.h"
#include "caresize.h"
#include "intelligentresizeutility.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
    ~MainWindow();

    QGraphicsItem * getPixmapItem();

private slots:
    void newFile();
    void open();
    void save();
    void saveAs();
    void openRecentFile();
    void closeCur();
    void undo();
    void redo();
    void zoomIn();
    void zoomOut();
    void cropInit();
    void resizeSwitch(QSize size, int filter);
    void setMerge(LImage other, double coef);
    void scissorsInit();
    void intelResizeHeight();
    void execIntelResizeHeight(int);
    void intelResizeWidth();
    void execIntelResizeWidth(int);
    void rotateCW();
    void rotateCCW();
    void normalSize();
    void fitInWindow();
    void fillWindow();

    //Filters
    void blur();
    void gaussBlur();
    void sharpen();
    void edgeDetect();
    void sobel();
    void emboss();

    //FFT
    void blurFFT();
    void gaussBlurFFT();
    void sharpenFFT();
    void edgeDetectFFT();
    void sobelFFT();
    void embossFFT();

    //Histogram Modifications
    void toNegative();
    void histogramStretch();
    void histogramHSIStretch();
    void histogramEqu();
    void histogramHSIEqu();
    void toGrayscale();

    void customConvolutionInit();
    void customConvolution(double* matrix, int width, int height);
    void about();

    void showResizeDialog();
    void showMergeDialog();
    void updateCoordLabel(QGraphicsSceneMouseEvent *e);
    void updateInfoDock(QGraphicsSceneMouseEvent *event);
protected:
    void keyPressEvent(QKeyEvent *event);
private:
    enum Mode
    {
        cropping = 0,
        mergeDiag,
        merging,
        resizing,
        intelResizeH,
        intelResizeW,
        scissors,
        normal
    };
    void setMode(Mode mode);
    void cancelCurMode();
    void switchToMode(Mode mode);
    Mode mode();
    void createActions();
    void createMenus();
    void createStatusBar();
    void createDockWidgets();
    void loadFile(const QString &fileName);
    bool saveFile(const QString &fileName);
    void setCurrentFile(const QString &fileName);
    void updateMenuActions(bool value);
    void updateRecentFileActions();
    void scaleView(qreal factor);
    void applyCrop(QRectF cropRect);
    void applyMerge(QRectF cropRect);
    QImage applyRotate();
    void rotate(qreal angle);
    void updateZoomLabel();
    void updateDisplay();
    void setUndo();

    QGraphicsView *graphicsView;
    ImageScene *imageScene;
    QGraphicsPixmapItem *imagePixmapItem;
    THGraphicsCropItem *cropSelection;
    THGraphicsMergeItem *mergeItem;
    HistogramWidget *histogramDock;

    QSlider *vSlider;
    QSlider *hSlider;
    Caresize *caresizeV;
    Caresize *caresizeH;

    QStatusBar *sB;
    QLabel *coordSB;
    QLabel *zoomSB;

    int zoomLevel;
    int rotationAngle;

    LImage image;
    /*
    LImage redoimage;
    int redoim;
    int maxUndo;
    LImage undoIm[3];
    int readyUndo;
    int numUndo;
*/
    LImage redoimage;
    LImage undoimage;
    int undoDone;
    int undoReady;

    LImage m_other;
    double m_coef;
    int m_posx;
    int m_posy;

    // Scissor
    bool scissor_flag;
    unsigned int x1_scissor,y1_scissor;
    IntelligentResizeUtility *intelligent;

    // dock widgets (pixel Information Dock)
    QLabel *xl;
    QLabel *yl;
    QLabel *lR;
    QLabel *lG;
    QLabel *lB;
    QLabel *lY;
    QLabel *lU;
    QLabel *lV;

    QString winTitle;
    QString pathName;
    QFileInfo *curFileInfo;
    Mode execution;
    QErrorMessage *instructions;

    QMenu *fileMenu;
    QMenu *recentFilesMenu;
    QMenu *editMenu;
    QMenu *viewMenu;
    QMenu *zoomMenu;
    QMenu *filtersMenu;
    QMenu *blurMenu;
    QMenu *sharpenMenu;
    QMenu *edgeDetectMenu;
    QMenu *helpMenu;
    QMenu *transformMenu;
    QMenu *FFTMenu;
    QMenu *blurFFTMenu;
    QMenu *sharpenFFTMenu;
    QMenu *edgeDetectFFTMenu;

    //File
    QAction *newAct;
    QAction *openAct;
    QAction *saveAct;
    QAction *saveAsAct;
    QAction *closeAct;
    QAction *closeWinAct;
    QAction *quitAct;

    //Edit
    QAction *undoAct;
    QAction *redoAct;
    QAction *cropAct;
    QAction *resizeAct;
    QAction *mergeAct;
    QAction *intelligentResizeVAct;
    QAction *intelligentResizeHAct;
    QAction *intelligentScissorsAct;
    QAction *rotateCAct;
    QAction *rotateACAct;

    //View
    QAction *zoomInAct;
    QAction *zoomOutAct;
    QAction *normalSizeAct;
    QAction *fitInWindowAct;
    QAction *fillWindowAct;

    //Filter Actions
    QAction *blurAct;
    QAction *gaussBlurAct;
    QAction *sharpenAct;
    QAction *edgeDetectAct;
    QAction *sobelAct;
    QAction *embossAct;
    QAction *customConvolutionAct;

    //FFT Actions
    QAction *blurFFTAct;
    QAction *gaussBlurFFTAct;
    QAction *sharpenFFTAct;
    QAction *edgeDetectFFTAct;
    QAction *sobelFFTAct;
    QAction *embossFFTAct;

    //Transform Actions
    QAction *negativeAct;
    QAction *histogramStretchAct;
    QAction *histogramHSIStretchAct;
    QAction *histogramEquAct;
    QAction *histogramHSIEquAct;
    QAction *toGrayscaleAct;

    QAction *aboutAct;
    QAction *aboutQtAct;

    enum { MaxRecentFiles = 5 };
    QAction *recentFileActs[MaxRecentFiles];
};

#endif // MAINWINDOW_H
